package com.ni.learning.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ni.learning.exam.dto.EnterExamDTO;
import com.ni.learning.exam.dto.ExamDTO;
import com.ni.learning.exam.mapper.ExamMapper;
import com.ni.learning.exam.service.AnswerSheetService;
import com.ni.learning.exam.service.ExamService;
import com.ni.learning.exam.vo.AnswerSheetVO;
import com.ni.learning.exam.vo.ExamVO;
import com.our.learning.infrastructure.constant.ResponseStatusEnum;
import com.our.learning.infrastructure.po.AnswerSheet;
import com.our.learning.infrastructure.po.Exam;
import com.our.learning.infrastructure.pojo.Response;
import com.our.learning.infrastructure.utils.DateUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : Ice'Clean
 * @date : 2023-06-07
 */
@Service
public class ExamServiceImpl implements ExamService {

    private final ExamMapper examMapper;
    private final AnswerSheetService answerSheetService;

    public ExamServiceImpl(ExamMapper examMapper, AnswerSheetService answerSheetService) {
        this.examMapper = examMapper;
        this.answerSheetService = answerSheetService;
    }

    private Exam getExamById(int examId) {
        return examMapper.selectById(examId);
    }

    @Override
    public Response getExam(int examId) {
        Exam exam = getExamById(examId);
        if (exam == null) {
            return new Response(ResponseStatusEnum.BAD_REQUEST)
                    .setMsg("不存在的考试");
        }
        ExamVO examVO = new ExamVO(exam);

        return new Response(ResponseStatusEnum.OK)
                .addData("nowTimestamp", DateUtils.getTimestamp())
                .addData("exam", examVO);
    }

    @Override
    public Response createExam(ExamDTO examDTO) {
        // 检查考试时间是否冲突
        String conflictInfo = checkConflict(examDTO);
        if (conflictInfo != null) {
            return new Response(ResponseStatusEnum.TIME_CONFLICT)
                    .addData("detail", conflictInfo);
        }
        // 持久化考试信息
        Exam exam = examDTO.getExam();
        if (examMapper.insert(exam) != 1) {
            return new Response(ResponseStatusEnum.DATABASE_ERROR);
        }
        // 创建成功并返回考试 ID
        return new Response(ResponseStatusEnum.OK)
                .addData("examId", exam.getId());
    }

    @Override
    public Response modifyExam(ExamDTO examDTO) {
        // 检查是否修改了时间
        if (examDTO.getStartTime() != null || examDTO.getEndTime() != null) {
            // 修改了时间，则检查是否冲突
            String conflictInfo = checkConflict(examDTO);
            if (conflictInfo != null) {
                return new Response(ResponseStatusEnum.TIME_CONFLICT)
                        .addData("detail", conflictInfo);
            }
        }
        // 执行修改
        Exam exam = examDTO.getExam();
        examMapper.updateById(exam);
        // 返回修改后的考试信息
        return new Response(ResponseStatusEnum.OK)
                .addData("exam", exam);
    }

    @Override
    public Response deleteExam(int examId) {
        // 查找指定的考试
        if (examMapper.deleteById(examId) != 1) {
            return new Response(ResponseStatusEnum.BAD_REQUEST)
                    .setMsg("考试 ID 对应的考试不存在");
        }
        return new Response(ResponseStatusEnum.OK);
    }

    @Override
    public Response studentExamList(int userId, int page, int perPage) {
        int start = (page - 1) * perPage;
        // TODO 查询学生信息
        // Student student = studentMapper.selectById(userId);
        // TODO 查询学生所在年级、所在班级所有考试
        List<Exam> examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .orderByAsc(true, Exam::getStartTime)
                .last(String.format("limit %d, %d", start, perPage)));
        //        .eq(Exam::getMajorId, student.getMajorId())
        //        .or()
        //        .eq(Exam::getClassId, student.getClassId()));
        // 转成 VO 对象
        List<ExamVO> examVOList = examList.stream().map(ExamVO::new).collect(Collectors.toList());
        return new Response(ResponseStatusEnum.OK)
                .addData("nowTimestamp", DateUtils.getTimestamp())
                .addData("examList", examVOList);
    }

    @Override
    public Response teacherExamList(int teacherId, int page, int perPage) {
        int start = (page - 1) * perPage;
        List<Exam> examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .orderByAsc(Exam::getStartTime)
                .eq(Exam::getTeacherId, teacherId)
                .last(String.format("limit %d, %d", start, perPage)));
        List<ExamVO> examVOList = examList.stream()
                .map(ExamVO::new).collect(Collectors.toList());
        return new Response(ResponseStatusEnum.OK)
                .addData("nowTimestamp", DateUtils.getTimestamp())
                .addData("examList", examVOList);
    }


    @Override
    public Response enterExam(EnterExamDTO enterExamDTO, boolean isTeacher) {
        int studentId = enterExamDTO.getStudentId();
        int examId = enterExamDTO.getExamId();
        // 查询指定考试
        Exam exam = getExamById(examId);
        if (exam == null) {
            return new Response(ResponseStatusEnum.BAD_REQUEST)
                    .setMsg("不存在的考试");
        }
        // 检查考试状态
        if (!isTeacher) {
            String examStatus = checkExam(exam);
            if (examStatus != null) {
                // 考试未开始或已结束
                return new Response(ResponseStatusEnum.BAD_REQUEST)
                        .setMsg(examStatus);
            }
        }
        // 查询学生答题卡
        AnswerSheet answerSheet = answerSheetService.getAnswerSheetByStudentExam(studentId, examId);
        // 检查第一次进入
        if (answerSheet == null) {
            // 创建空白答题卡
            answerSheet = answerSheetService.createAnswerSheet(studentId, examId, exam.getPaperId());
        }
        // 返回学生答卷
        return new Response(ResponseStatusEnum.OK)
                .addData("exam", new ExamVO(exam))
                .addData("answerSheet", new AnswerSheetVO(answerSheet));
    }

    @Override
    public Response publishResult(int examId) {
        // 查询考试
        Exam exam = getExamById(examId);
        // 修改状态
        exam.setChecked(1);
        return new Response(ResponseStatusEnum.OK);
    }

    /**
     * 检查考试时间是否冲突
     *
     * @param examDTO 考试数据
     * @return 冲突信息，否则返回 null
     */
    private String checkConflict(ExamDTO examDTO) {
//        //Exam exam = examMapper.selectOne(new LambdaQueryWrapper<Exam>()
//                //.lt(Exam::getStartTime));
//        //if (exam != null) {
//            // 与现有考试冲突了
//            return exam.getName();
//        }
        return null;
    }

    private String checkExam(Exam exam) {
        // 获取当前时间戳
        Long nowTimestamp = DateUtils.getTimestamp();
        // 获取考试开始和结束的时间戳
        Long startTimestamp = DateUtils.parseToTimestamp(exam.getStartTime());
        Long endTimestamp = DateUtils.parseToTimestamp(exam.getEndTime());
        if (nowTimestamp < startTimestamp) {
            return "考试未开始";
        }
        if (endTimestamp < nowTimestamp) {
            return "考试已结束";
        }
        return null;
    }
}
